using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using WpfApp3.Tools.Helper;

namespace WpfApp3.Controls;

public class TabPanel : Panel
{
    private int _itemCount;

    /// <summary>
    ///     是否可以更新
    /// </summary>
    internal bool CanUpdate = true;

    /// <summary>
    ///     选项卡字典
    /// </summary>
    internal Dictionary<int, TabItem> ItemDic = new();

    public static readonly DependencyPropertyKey FluidMoveDurationPropertyKey =
        DependencyProperty.RegisterReadOnly("FluidMoveDuration", typeof(Duration), typeof(TabPanel),
            new PropertyMetadata(new Duration(TimeSpan.FromMilliseconds(0))));

    /// <summary>
    ///     流式行为持续时间
    /// </summary>
    public static readonly DependencyProperty FluidMoveDurationProperty =
        FluidMoveDurationPropertyKey.DependencyProperty;

    /// <summary>
    ///     流式行为持续时间
    /// </summary>
    public Duration FluidMoveDuration
    {
        get => (Duration)GetValue(FluidMoveDurationProperty);
        set => SetValue(FluidMoveDurationProperty, value);
    }

    /// <summary>
    ///     标签宽度
    /// </summary>
    public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register(
        nameof(ItemWidth), typeof(double), typeof(TabPanel), new PropertyMetadata(200.0));

    /// <summary>
    ///     标签宽度
    /// </summary>
    public double ItemWidth
    {
        get => (double)GetValue(ItemWidthProperty);
        set => SetValue(ItemWidthProperty, value);
    }

    /// <summary>
    ///     标签高度
    /// </summary>
    public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register(
        nameof(ItemHeight), typeof(double), typeof(TabPanel), new PropertyMetadata(30.0));

    /// <summary>
    ///     标签高度
    /// </summary>
    public double ItemHeight
    {
        get => (double)GetValue(ItemHeightProperty);
        set => SetValue(ItemHeightProperty, value);
    }

    /// <summary>
    /// 方向的依赖属性
    /// </summary>
    public static readonly DependencyProperty OrientationProperty =
        DependencyProperty.Register("Orientation", typeof(Orientation), typeof(TabPanel),
            new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));

    /// <summary>
    /// 获取或设置面板的方向
    /// </summary>
    public Orientation Orientation
    {
        get { return (Orientation)GetValue(OrientationProperty); }
        set { SetValue(OrientationProperty, value); }
    }

    /// <summary>
    ///     是否可以强制更新
    /// </summary>
    internal bool ForceUpdate;

    private Size _oldSize;

    /// <summary>
    ///     是否已经加载
    /// </summary>
    private bool _isLoaded;

    protected override Size MeasureOverride(Size constraint)
    {
        if ((_itemCount == InternalChildren.Count || !CanUpdate) && !ForceUpdate)
            return _oldSize;


        if (Orientation == Orientation.Horizontal)
        {
            constraint.Height = ItemHeight;
        }
        else
        {
            constraint.Width = ItemWidth;
        }

        _itemCount = InternalChildren.Count;

        var size = new Size();

        ItemDic.Clear();

        var count = InternalChildren.Count;
        if (count == 0)
        {
            _oldSize = new Size();
            return _oldSize;
        }
        if (Orientation == Orientation.Horizontal)
        {
            constraint.Width += InternalChildren.Count;
        }
        else
        {
            constraint.Height += InternalChildren.Count;
        }

        for (var index = 0; index < count; index++)
        {
            if (InternalChildren[index] is TabItem tabItem)
            {
                tabItem.RenderTransform = new TranslateTransform();


                if (Orientation == Orientation.Horizontal)
                {
                    tabItem.MaxWidth = ItemWidth;
                    var rect = new Rect
                    {
                        X = size.Width - tabItem.BorderThickness.Left,
                        Width = ItemWidth,
                        Height = ItemHeight
                    };
                    tabItem.Arrange(rect);
                    tabItem.ItemWidth = ItemWidth - tabItem.BorderThickness.Left;
                    tabItem.CurrentIndex = index;
                    tabItem.TargetOffsetX = 0;
                    tabItem.TargetOffsetY = 0;
                    ItemDic[index] = tabItem;
                    size.Width += tabItem.ItemWidth;
                }
                else
                {
                    tabItem.MaxHeight = ItemHeight;
                    var rect = new Rect
                    {
                        Y = size.Height - tabItem.BorderThickness.Top,
                        Width = ItemWidth,
                        Height = ItemHeight
                    };
                    tabItem.Arrange(rect);
                    tabItem.ItemHeight = ItemHeight - tabItem.BorderThickness.Top;
                    tabItem.CurrentIndex = index;
                    tabItem.TargetOffsetY = 0;
                    ItemDic[index] = tabItem;
                    size.Height += tabItem.ItemHeight;
                }
            }
        }
        if (Orientation == Orientation.Horizontal)
        {
            size.Height = constraint.Height;
        }
        else
        {
            size.Width = constraint.Width;
        }
        _oldSize = size;
        return _oldSize;
    }

    public TabPanel()
    {
        Loaded += (s, e) =>
        {
            if (_isLoaded) return;
            ForceUpdate = true;
            if (Orientation == Orientation.Horizontal)
            {
                Measure(new Size(DesiredSize.Width, ActualHeight));
            }
            else
            {
                Measure(new Size(ActualWidth, DesiredSize.Height));
            }
            ForceUpdate = false;
            foreach (var item in ItemDic.Values)
            {
                item.TabPanel = this;
            }
            _isLoaded = true;
        };
    }
}
